home *** CD-ROM | disk | FTP | other *** search
/ Aminet 32 / Aminet 32 (1999)(Schatztruhe)[!][Aug 1999].iso / Aminet / dev / lang / Python152.lha / Python-1.5 / Demo / metaclasses / Meta.py < prev    next >
Text File  |  1998-09-14  |  3KB  |  121 lines

  1. """Generic metaclass.
  2.  
  3. XXX This is very much a work in progress.
  4.  
  5. """
  6.  
  7. import types
  8.  
  9. class MetaMethodWrapper:
  10.  
  11.     def __init__(self, func, inst):
  12.         self.func = func
  13.         self.inst = inst
  14.         self.__name__ = self.func.__name__
  15.  
  16.     def __call__(self, *args, **kw):
  17.         return apply(self.func, (self.inst,) + args, kw)
  18.  
  19. class MetaHelper:
  20.  
  21.     __methodwrapper__ = MetaMethodWrapper # For derived helpers to override
  22.  
  23.     def __helperinit__(self, formalclass):
  24.         self.__formalclass__ = formalclass
  25.  
  26.     def __getattr__(self, name):
  27.         # Invoked for any attr not in the instance's __dict__
  28.         try:
  29.             raw = self.__formalclass__.__getattr__(name)
  30.         except AttributeError:
  31.             try:
  32.                 ga = self.__formalclass__.__getattr__('__usergetattr__')
  33.             except KeyError:
  34.                 raise AttributeError, name
  35.             return ga(self, name)
  36.         if type(raw) != types.FunctionType:
  37.             return raw
  38.         return self.__methodwrapper__(raw, self)
  39.  
  40. class MetaClass:
  41.  
  42.     """A generic metaclass.
  43.  
  44.     This can be subclassed to implement various kinds of meta-behavior.
  45.  
  46.     """
  47.  
  48.     __helper__ = MetaHelper             # For derived metaclasses to override
  49.  
  50.     __inited = 0
  51.  
  52.     def __init__(self, name, bases, dict):
  53.         try:
  54.             ga = dict['__getattr__']
  55.         except KeyError:
  56.             pass
  57.         else:
  58.             dict['__usergetattr__'] = ga
  59.             del dict['__getattr__']
  60.         self.__name__ = name
  61.         self.__bases__ = bases
  62.         self.__realdict__ = dict
  63.         self.__inited = 1
  64.  
  65.     def __getattr__(self, name):
  66.         try:
  67.             return self.__realdict__[name]
  68.         except KeyError:
  69.             for base in self.__bases__:
  70.                 try:
  71.                     return base.__getattr__(name)
  72.                 except AttributeError:
  73.                     pass
  74.             raise AttributeError, name
  75.  
  76.     def __setattr__(self, name, value):
  77.         if not self.__inited:
  78.             self.__dict__[name] = value
  79.         else:
  80.             self.__realdict__[name] = value
  81.  
  82.     def __call__(self, *args, **kw):
  83.         inst = self.__helper__()
  84.         inst.__helperinit__(self)
  85.         try:
  86.             init = inst.__getattr__('__init__')
  87.         except AttributeError:
  88.             init = lambda: None
  89.         apply(init, args, kw)
  90.         return inst
  91.     
  92.  
  93. Meta = MetaClass('Meta', (), {})
  94.  
  95.  
  96. def _test():
  97.     class C(Meta):
  98.         def __init__(self, *args):
  99.             print "__init__, args =", args
  100.         def m1(self, x):
  101.             print "m1(x=%s)" %`x`
  102.     print C
  103.     x = C()
  104.     print x
  105.     x.m1(12)
  106.     class D(C):
  107.         def __getattr__(self, name):
  108.             if name[:2] == '__': raise AttributeError, name
  109.             return "getattr:%s" % name
  110.     x = D()
  111.     print x.foo
  112.     print x._foo
  113. ##     print x.__foo
  114. ##     print x.__foo__
  115.  
  116.  
  117. if __name__ == '__main__':
  118.     _test()
  119.  
  120.     
  121.